from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
import pandas as pd
import time
import random
import json
import threading

# 店铺URL映射
STORE_URLS = {
    '安德玛': {
        'primary': 'https://mall.jd.com/index-1000399942.html?from=pc',
        'backup': 'https://mall.jd.com/view_search-1000399942-0-0-0-1-0-0-1-1-24.html'
    },
    '耐克': {
        'primary': 'https://mall.jd.com/view_search-1005989-786896-782694-0-0-0-0-1-1-60.html?keyword=JG5922',
        'backup': 'https://mall.jd.com/index-1000001927.html?from=pc'
    },
    '阿迪达斯': {
        'primary': 'https://mall.jd.com/view_search-1005989-786896-782694-0-0-0-0-1-1-60.html?keyword=JG5922',
        'backup': 'https://mall.jd.com/view_search-467302-1000005792-1000005792-0-1-0-0-1-1-24.html?keyword=JH6961&isGlobalSearch=1'
    },
    '彪马': {
        'primary': 'https://mall.jd.com/advance_search-103495-35967-34239-0-0-0-1-1-60.html?keyword=399152',
        'backup': 'https://mall.jd.com/view_search-103495-0-0-0-1-0-0-1-1-24.html'
    }
}

class PriceMonitor:
    def __init__(self):
        self.price = None
        self.price_found = threading.Event()

def attach_to_chrome():
    """连接到已经打开的Chrome浏览器"""
    try:
        print("尝试连接Chrome...")
        chrome_options = Options()
        chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
        chrome_driver_path = r'C:\Program Files\Google\Chrome\Application\chromedriver.exe'
        service = Service(executable_path=chrome_driver_path)
        driver = webdriver.Chrome(service=service, options=chrome_options)
        print("Chrome连接成功！")
        return driver
    except Exception as e:
        print(f"Chrome连接失败: {e}")
        raise

def search_product(driver, search_text):
    """在店铺内搜索商品"""
    try:
        # 等待搜索框出现
        search_input = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "J_shopLinkSearchInput"))
        )
        search_input.clear()
        search_input.send_keys(search_text)

        # 点击搜索按钮
        search_button = driver.find_element(By.CLASS_NAME, "s-submit")
        search_button.click()
        # 等待搜索结果加载
        WebDriverWait(driver, 7).until(
            EC.presence_of_element_located((By.CLASS_NAME, "jSearchList"))
        )
    except Exception as e:
        print(f"搜索出错: {e}")

def extract_product_info(driver, product_code):
    """提取商品信息"""
    results = []
    try:
        # 确保product_code是字符串类型
        product_code = str(product_code) if product_code is not None else ""

        items = driver.find_elements(By.CLASS_NAME, "jSubObject")
        for item in items:
            try:
                # 获取商品名称并打印HTML
                name_element = item.find_element(By.CLASS_NAME, "jDesc")
                html_content = name_element.get_attribute('innerHTML')
                #print("原始HTML内容:", html_content)

                # 尝试获取商品编号 - 修改获取方式
                try:
                    # 直接从innerHTML中提取商品编号
                    if '<font class="skcolor_ljg">' in html_content:
                        sku_code = html_content.split('<font class="skcolor_ljg">')[1].split('</font>')[0]
                        #print("找到商品编号:", sku_code)
                        # 获取完整的商品名称
                        full_name = name_element.text
                        # 在尺码前插入商品编号
                        parts = full_name.split(" ")
                        # 在倒数第二个位置插入商品编号
                        parts.insert(-1, sku_code)
                        name = " ".join(parts)
                    else:
                        name = name_element.text
                except Exception as e:
                    print(f"获取商品编号出错: {e}")
                    name = name_element.text

                print(f"商品名称: {name}")

                # 检查商品编号是否匹配
                if product_code.lower() in name.lower():
                    # 保存当前URL
                    current_url = driver.current_url

                    # 找到商品图片链接
                    print("找到匹配商品...")
                    product_link = item.find_element(By.CSS_SELECTOR, ".jPic a")
                    link = product_link.get_attribute("href")

                    try:
                        print("点击进入详情页...")
                        # 在点击商品链接前读取price.json的url字段
                        with open('price.json', 'r', encoding='utf-8') as f:
                            price_data = json.load(f)
                            initial_url_value = price_data['url']

                        product_link.click()
                        time.sleep(random.uniform(1, 1.4))

                        # 保存当前窗口句柄
                        original_window = driver.current_window_handle

                        # 切换到新打开的标签页
                        for window_handle in driver.window_handles:
                            if window_handle != original_window:
                                driver.switch_to.window(window_handle)
                                break

                        # 循环读取price.json的url字段10秒
                        success = False
                        price_data = None

                        for _ in range(20):  # 改为20次，每次0.5秒，总共10秒
                            time.sleep(0.5)
                            try:
                                with open('price.json', 'r', encoding='utf-8') as f:
                                    price_data = json.load(f)
                                    if price_data['url'] != initial_url_value:
                                        success = True
                                        break
                            except json.JSONDecodeError:
                                continue  # 如果文件正在写入，跳过这次读取

                        # 判断价格获取是否成功
                        price = "价格获取失败"
                        if success and price_data:
                            try:
                                content = json.loads(price_data['content'])
                                if 'price' in content and 'p' in content['price']:
                                    price = content['price']['p']
                                    print(f"获取到价格: {price}")
                                else:
                                    print("未找到价格字段")
                            except:
                                print("解析价格数据失败")

                        # 关闭当前标签页并切回原标签页
                        driver.close()
                        driver.switch_to.window(original_window)
                        time.sleep(0.5)  # 等待切换完成

                        results.append({
                            'link': link,
                            'price': price
                        })

                        # 找到匹配商品后就返回
                        return results

                    except Exception as e:
                        print(f"获取价格出错: {e}")
                        # 确保关闭新标签页并返回原标签页
                        try:
                            if len(driver.window_handles) > 1:
                                driver.close()
                                driver.switch_to.window(original_window)
                        except:
                            pass
                        price = "价格获取失败"
                        results.append({
                            'link': link,
                            'price': price
                        })
                        return results

            except Exception as e:
                print(f"处理商品项时出错: {e}")
                continue

    except Exception as e:
        print(f"提取商品信息出错: {e}")

    return results

def try_search_in_store(driver, product_code, store_url):
    """在指定店铺URL中尝试搜索商品"""
    try:
        print(f"尝试URL: {store_url}")
        driver.get(store_url)
        #time.sleep(1)

        # 搜索商品
        search_product(driver, product_code)
        #time.sleep(0.5)

        # 提取商品信息
        return extract_product_info(driver, product_code)
    except Exception as e:
        print(f"在URL {store_url} 搜索时出错: {e}")
        return None

def get_price_from_link(driver, link):
    """从商品链接直接获取价格"""
    try:
        print(f"从链接直接获取价格: {link}")
        # 保存当前窗口句柄
        original_window = driver.current_window_handle

        # 保存初始url值
        with open('price.json', 'r', encoding='utf-8') as f:
            price_data = json.load(f)
            initial_url_value = price_data['url']

        # 定义多个 referer，包含 None 表示无 referer
        referers = [
            'https://pro.jd.com/mall/active/2Ju6KX27EyzyzLKZMHcNKNwomHh1/index.html?babelChannel=ttt1',
            'https://pro.jd.com/mall/active/2evvPWwD9tbuxiDdBEqF8i4DxWjS/index.html?innerAnchor=324843',
            'https://cfe.m.jd.com/',
            'https://pro.jd.com/mall/active/2evvPWwD9tbuxiDdBEqF8i4DxWjS/index.html?innerAnchor=4134901',
            None  # 表示无 referer
        ]

        # 随机选择一个 referer
        selected_referer = random.choice(referers)
        print(f"使用 Referer: {'无' if selected_referer is None else selected_referer}")

        # 设置请求头
        headers = {'headers': {}} if selected_referer is None else {'headers': {'Referer': selected_referer}}
        driver.execute_cdp_cmd('Network.setExtraHTTPHeaders', headers)

        # 打开新标签页访问链接
        driver.execute_script(f"window.open('{link}');")
        time.sleep(random.uniform(2.3, 3.2))

        # 切换到新标签页
        for window_handle in driver.window_handles:
            if window_handle != original_window:
                driver.switch_to.window(window_handle)
                break

        # 等待并获取价格
        success = False
        price_data = None
        for _ in range(20):  # 10秒超时
            time.sleep(0.5)
            try:
                with open('price.json', 'r', encoding='utf-8') as f:
                    price_data = json.load(f)
                    if price_data['url'] != initial_url_value:
                        success = True
                        break
            except json.JSONDecodeError:
                continue

        # 解析价格
        price = "价格获取失败"
        if success and price_data:
            try:
                content = json.loads(price_data['content'])
                if 'price' in content and 'p' in content['price']:
                    price = content['price']['p']
                    print(f"获取到价格: {price}")
                else:
                    print("未找到价格字段")
            except:
                print("解析价格数据失败")

        # 关闭新标签页并返回原标签页
        time.sleep(random.uniform(0.5, 1.3))
        driver.close()
        driver.switch_to.window(original_window)

        return price

    except Exception as e:
        print(f"从链接获取价格时出错: {e}")
        # 确保关闭新标签页
        try:
            if len(driver.window_handles) > 1:
                driver.close()
                driver.switch_to.window(original_window)
        except:
            pass
        return "价格获取失败"

def main():
    print('now read')
    df = pd.read_csv('jd-nike.csv', encoding='gbk')

    print('now driver chrome ing')
    driver = attach_to_chrome()
    print('now driver chrome success')

    for index, row in df.iterrows():
        try:
            # 如果链接存在但价格为空，直接从链接获取价格
            if pd.notna(row['链接']) and row['链接'] != "无数据" and \
                    (pd.isna(row['店铺价']) or row['店铺价'] == "无数据"):
                print(f"\n处理第 {index + 1} 行: 从现有链接获取价格")
                price = get_price_from_link(driver, row['链接'])
                df.at[index, '店铺价'] = price
                df.to_csv('jd-nike.csv', index=False, encoding='gbk')
                continue

            # 如果链接和价格都存在，跳过
            if pd.notna(row['店铺价']) and pd.notna(row['链接']) and \
                    row['店铺价'] != "无数据" and row['链接'] != "无数据":
                print(f"\n跳过第 {index + 1} 行: 已处理")
                continue

            # 原有的搜索逻辑保持不变
            brand = row['产品品牌']
            product_code = row['产品规格']

            # 确定要访问的店铺URL
            store_urls = STORE_URLS.get(brand)
            if not store_urls:
                df.at[index, '店铺价'] = "无数据"
                df.at[index, '链接'] = "无数据"
                print(f"未找到品牌 {brand} 对应的店铺")
                df.to_csv('jd-nike.csv', index=False, encoding='gbk')
                continue

            try:
                # 依次尝试主要URL和备用URL
                found_product = False
                urls_to_try = [store_urls['primary']]

                # 检查当前URL，如果已经在正确的页面就不需要跳转
                current_url = driver.current_url
                if ('view_search' in current_url and brand in ['彪马', '阿迪达斯', '耐克']) or \
                        (any(store_id in current_url for store_id in ['1000399942', '1000001927', '1000005792', '1000106661'])):
                    print("已在正确的店铺页面，直接搜索")
                    results = try_search_in_store(driver, product_code, current_url)
                    if results:
                        found_product = True
                        link = results[0]['link']
                        price = results[0]['price']
                        df.at[index, '链接'] = link
                        df.at[index, '店铺价'] = price
                        print(f"在当前页面找到商品:")
                        print(f"价格: {price}")
                        print(f"链接: {link}")

                # 如果当前页面没找到，尝试其他URL
                if not found_product:
                    urls_to_try.append(store_urls['backup'])
                    for url in urls_to_try:
                        results = try_search_in_store(driver, product_code, url)
                        if results:
                            found_product = True
                            link = results[0]['link']
                            price = results[0]['price']
                            df.at[index, '链接'] = link
                            df.at[index, '店铺价'] = price
                            print(f"在URL {url} 中找到商品:")
                            print(f"价格: {price}")
                            print(f"链接: {link}")
                            break

                # 如果所有URL都没找到
                if not found_product:
                    df.at[index, '店铺价'] = "无数据"
                    df.at[index, '链接'] = "无数据"
                    print("在所有URL中都未找到匹配的商品")

                # 实时保存到CSV
                df.to_csv('jd-nike.csv', index=False, encoding='gbk')

            except Exception as e:
                print(f"处理行 {index} 时出错: {e}")
                df.at[index, '店铺价'] = "无数据"
                df.at[index, '链接'] = "无数据"
                df.to_csv('jd-nike.csv', index=False, encoding='gbk')
                continue

        except Exception as e:
            print(f"处理行 {index} 时出错: {e}")
            if pd.isna(row['店铺价']):
                df.at[index, '店铺价'] = "无数据"
            if pd.isna(row['链接']):
                df.at[index, '链接'] = "无数据"
            df.to_csv('jd-nike.csv', index=False, encoding='gbk')
            continue

    driver.quit()

if __name__ == "__main__":
    main() 